package com.cy.pj.sys.service.impl;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.exception.ServiceException;
import com.cy.pj.common.pojo.PageObject;
import com.cy.pj.sys.dao.SysUserDao;
import com.cy.pj.sys.dao.SysUserRoleDao;
import com.cy.pj.sys.pojo.SysUser;
import com.cy.pj.sys.service.SysUserService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Transactional(readOnly = false,
               rollbackFor = Throwable.class,
               isolation = Isolation.READ_COMMITTED,
               timeout = 5,
               propagation= Propagation.REQUIRED)
@Service
public class SysUserServiceImpl implements SysUserService {
    @Autowired
    private SysUserDao sysUserDao;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;

    public int updateObject(SysUser entity,Integer[]roleIds){
        //开启事务
        //1.参数校验(省略)
        //2.更新用户自身信息
        int rows=sysUserDao.updateObject(entity);
        if(rows==0)
            throw new ServiceException("记录可能已经不存在");
        //3.更新用户和角色关系数据
        sysUserRoleDao.deleteObjectsByUserId(entity.getId());
        sysUserRoleDao.insertObjects(entity.getId(),roleIds);
        //提交事务
        //回滚事务
        //释放资源
        return rows;
    }
    //@Transactional注解描述的方法为事务的切入点方法
    //此方法在执行时就会通过通知方法为其进行事务逻辑增强
    @Transactional(readOnly = true)
    public Map<String,Object> findById(Integer id){
        SysUser user=sysUserDao.findById(id);
        if(user==null)
            throw new ServiceException("此用户可能已经不存在");
        List<Integer> roleIds=sysUserRoleDao.findRoleIdsByUserId(id);
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("user",user);//这里的key不能随意写,要与客户端取值方式一致
        map.put("roleIds",roleIds);
        return map;
    }

    @Transactional(timeout = 5)
    public int saveObject(SysUser entity,Integer[]roleIds){
        //try{ Thread.sleep(20000);}catch(Exception e){}
        //参数校验(省略)
        //产生一个随机字符串作为加密盐使用
        String salt= UUID.randomUUID().toString();
        //对密码进行MD5盐值加密(MD5特点:不可逆,相同内容加密结果也相同)
        SimpleHash sh=new SimpleHash("MD5",entity.getPassword(),salt,1);
        String hashedPassword=sh.toHex();
        entity.setSalt(salt);
        entity.setPassword(hashedPassword);
        int rows=sysUserDao.insertObject(entity);
        sysUserRoleDao.insertObjects(entity.getId(),roleIds);

        return rows;
    }

    /**
     * @RequiresPermissions 描述的方法为切入点方法，此方法在执行时
     * 需要在"通知方法"中判定用户是否有访问此方法的权限(检测用户权限中
     * 是否包含@RequiresPermissions注解内部包含的权限)，假如有权限
     * 则授权访问。
     * @param id
     * @param valid
     * @return
     */
    @RequiresPermissions("sys:user:update")
    public int validById(Integer id,Integer valid){
        int rows=sysUserDao.validById(id,valid);
        if(rows==0)throw new ServiceException("记录可能已经不存在");
        return rows;
    }
    /**
     * @RequiredLog注解描述的方法为日志切入点方法
     * @param username
     * @param pageCurrent
     * @return
     */
    @RequiredLog("日志分页查询")
    public PageObject<SysUser> findPageObjects(
            String username, Integer pageCurrent){
        String tName=Thread.currentThread().getName();
        System.out.println("SysUserService.findPageObjects->"+tName);
        int pageSize=5;
        Page<SysUser> page= PageHelper.startPage(pageCurrent,pageSize);
        List<SysUser> records=sysUserDao.findPageObjects(username);
        return new PageObject((int)page.getTotal(),records,
                pageSize,pageCurrent);
    }
}
